// 工具函数
const { getOne, query } = require('./dbTools');
const jwt = require('jsonwebtoken')
const { secret } = require('../config/global')

/**
 * 检测数据是否已经存在
 * @param {string} table 数据表名称
 * @param {string} fieldName 字段名
 * @param {string} fieldValue 字段值
 * @return {Boolean} true表示可用, false表示不可用(已存在)
*/
const isValidator = async (table, fieldName, fieldValue) => {
    const res = await getOne(table, { [fieldName]: fieldValue });
    // 如果没有查询到结果, 说明可用
    if (!res) {
        return true;
    }
    // 数据已存在, 不可用
    return false;
}

/**
 * 检测数据是否已经存在
 * @param {string} table 数据表名称
 * @param {object} map 查询条件
 * @return {Boolean} true表示可用, false表示不可用(已存在)
*/
const isValidator2 = async (table, map) => {
    const res = await getOne(table, map);
    // 如果没有查询到结果, 说明可用
    if (!res) {
        return true;
    }
    // 数据已存在, 不可用
    return false;
}


/**
 * 检测数据是否已经存在
 * @param {string} table 数据表名称
 * @param {string} fieldName 字段名
 * @param {string} fieldValue 字段值
 * @return {Boolean} true表示可用, false表示不可用(已存在)
*/
const isValidator3 = async (sql) => {
    const res = await query(sql);
    // 如果没有查询到结果, 说明可用
    if (res.length == 0) {
        return true;
    }
    // 数据已存在, 不可用
    return false;
}

/**
 * 检测当前节点是否存在子节点
 * @param {number} pid 节点pid
 * @param {string} table 数据表名
 * 
*/
const hasChildNodes = async (table, pid) => {
    const res = await getOne(table, { pid });
    if (res) {
        return true;
    }
    return false;
}


/**
 * 将普通数组转为树形数组
 * @param {array} arr 待转换普通数组
 * @return {array} 树形数组
 * */


const arrToTree = (arr) => {
    // 创建一个对象, 用来保存以数组元素的id为key, 数组元素为value的键值对
    const map = {};
    // 用户保存转换结果的数组
    const tree = [];
    arr.forEach(item => {
        map[item.id] = item;
    });

    arr.forEach(item => {
        // 先将一级节点元素保存到结果数组tree中
        if (item.pid === 0) {
            tree.push(item);
        } else {
            // 将非一级节点元素保存到对应的父级节点元素的children属性中
            if (map[item.pid] && !map[item.pid].children) {
                map[item.pid].children = [];
            }
            if (map[item.pid] && map[item.pid].children) {
                map[item.pid].children.push(item);
            }
        }
    });
    return tree;
}

/**
 * 根据关键词搜索树形数组, 并返回索引路径
 * @param {array} tree 待搜索树形数组
 * @param {string} keywords 搜索关键词
 * @param {string} attr 使用关键词和数组元素对象中那个属性进行匹配
*/

const searchTree = (tree, keywords, attr = 'name') => {
    const path = [];
    for (let index in tree) {
        path = [index];
        const value = tree[index];
        if (value[attr] === keywords) {
            return path;
        }
        // 递归
        const result = searchTree(value.children, keywords, attr);
        if (result && result.length > 0) {
            // 将本地结果拼接到上次的结果之后并返回
            return path.concat(result);
        }
    }
    // 将未匹配到的索引弹出
    path.pop();
    return [];
}

// 检查token是否过期
const verifyToken = (token) => {
    const output = {
        code: 200,
        msg: '登录凭证token合法有效'
    }
    try {
        var decoded = jwt.verify(token, secret);
        if (!decoded) {
            output.code = 403;
            output.msg = '登录凭证token不合法或已过期';
            return output;
        }
        const { exp } = decoded;
        // token过期
        if (exp * 1000 < Date.now()) {
            output.code = 403;
            output.msg = "登录凭证token已过期";
            return output;
        }
    } catch (err) {
        // err
        if (!decoded) {
            output.code = 403;
            output.msg = '登录凭证token不合法或已过期';
            return output;
        }
    }
    return output;
}



module.exports = {
    arrToTree,
    searchTree,
    isValidator,
    isValidator2,
    isValidator3,
    hasChildNodes,
    verifyToken
}